package com.atguigu.crowd.mvc.config;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.atguigu.crowd.constant.CrowdConstant;
import com.atguigu.crowd.exception.DuplicateKeyshengNameException;
import com.atguigu.crowd.exception.LoginAccAlreadInUserException;
import com.atguigu.crowd.exception.LoginFailedException;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;

//@ControllerAdvice表示当前类是一个基于注解的异常处理器类
@ControllerAdvice
public class CrowdExceptionResolver {

	//这个异常映射用于省份管理-新增时，账号重复的时候
	@ExceptionHandler(value = DuplicateKeyshengNameException.class)
	public ModelAndView  resolveshengNameDuplicateKeyException(
			DuplicateKeyshengNameException exception,
			HttpServletRequest request,
			HttpServletResponse response
			) {
		
		String viewName="sheng/sheng-add";//如果失败了，回到的页面
		
		return commonResolve(exception, request, response, viewName);
	}
	
	//这个异常映射用于管理员维护-新增时，账号重复的时候
	@ExceptionHandler(value = LoginAccAlreadInUserException.class)
	public ModelAndView  resolveLoginAccAlreadInUserException(
			LoginAccAlreadInUserException exception,
			HttpServletRequest request,
			HttpServletResponse response
			) {
		
		String viewName="admin-add";//如果失败了，回到的页面
		
		return commonResolve(exception, request, response, viewName);
	}
	
	//@ExceptionHandler将一个具体的异常类型和一个方法关联起来
	@ExceptionHandler(value = LoginFailedException.class)
	public ModelAndView  resolveLoginFailedException(
			ArithmeticException exception,	//ArithmeticException 是当出现异常的运算条件时，抛出此异常。例如，一个整数“除以零”时，抛出此类的一个实例
			HttpServletRequest request,
			HttpServletResponse response
			) {
		
		String viewName="admin-login";//登录如果失败了，还是再次回到登录页面
		
		return commonResolve(exception, request, response, viewName);
	}
	
	//处理空指针异常
	//@ExceptionHandler将一个具体的异常类型和一个方法关联起来
	@ExceptionHandler(value = NullPointerException.class)
	public ModelAndView  resolveNullPointerException(
			NullPointerException exception,
			HttpServletRequest request,
			HttpServletResponse response
			) {
		
		String viewName="system-error-resolveNullPointerException";//报错的时候返回这个jsp页面
		
		return commonResolve(exception, request, response, viewName);
	}
	//处理数学异常
	@ExceptionHandler(value=ArithmeticException.class)
	public ModelAndView resolveMathException(
			ArithmeticException exception,
			HttpServletRequest request,
			HttpServletResponse response
			) {
		
		String viewName="system-error-MathException";//报错的时候返回这个jsp页面
		
		return commonResolve(exception, request, response, viewName);
	}

	public ModelAndView commonResolve(
			//实际捕获到的异常类型
			Exception exception,
			//当前请求对象
			HttpServletRequest request,
			
			//// 当前响应对象
			HttpServletResponse response,
			
			// 异常处理完成后要去的页面
			String viewName
			) {
		
		//1、判断当前请求的请求类型
		boolean judgeResult=CrowdUtil.judgeRequestType(request);
		
		//2、判断 是否 是 ajax请求
		if(judgeResult) {
			
			//是  ajax请求
			
			//3、创建ResultEntity对象
			ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
			//4、创建Gson对象
			Gson gson=new Gson();
			//5、将ResultEntity对象转成json字符串
			String json = gson.toJson(resultEntity);
			//6、将json字符串作为相应体返回给浏览器
			try {
				response.getWriter().write(json);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//7、由于上面已经通过原生的response对象返回了响应了，所以就不需要再提供ModelAndView对象了
			return null;
		}
		
		//不是 ajax请求
		
		//8、如果不是ajax请求则需要创建ModelAndView对象
		ModelAndView modelAndView=new ModelAndView();
		
		//9、将Exception对象存入模型
		/*modelAndView.addObject("exception", exception);*/
		//用常量管理,代替上面的写法
		modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
		
		//10、设置对应的视图名称
		
		modelAndView.setViewName(viewName);
		
		//11、返回modelAndView
		return modelAndView;
	}
}













